﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TA.Turbo.Controls
{
	/// <summary>
	/// Definition of a property that exists both on client and server.
	/// </summary>
	/// <typeparam name="T">The type this property's value can take.</typeparam>
	public class PropertyDefinition<T> : BasePropertyDefinition
	{
		#region PUBLIC
		#region INIT
		/// <summary>
		/// Ctor.
		/// </summary>
		/// <param name="name"></param>
		/// <param name="shortName"></param>
		/// <param name="defaultValue"></param>
		public PropertyDefinition(string name, string shortName, T defaultValue)
			: base(name, shortName)
		{
			this._defaultValue = defaultValue;
		}
		#endregion
		#region PROPS
		/// <summary>
		/// Gets the default value for this property.
		/// </summary>
		public T DefaultValue
		{
			get
			{
				return this._defaultValue;
			}
		}
		#endregion
		#region METHODS
		/// <summary>
		/// Serializes the value of this property for the specified control to the specified <see cref="JsonWriter"/>.
		/// </summary>
		/// <param name="control"></param>
		/// <param name="jw"></param>
		protected override void DoSerializeValue(TControl control, TA.JSON.JsonWriter jw)
		{
			jw.Value(this.GetValue(control));
		}
		/// <summary>
		/// Returns true if the value of this property for the specified control is equal to the default, otherwise false.
		/// </summary>
		/// <param name="control"></param>
		/// <returns></returns>
		protected override bool ValueIsDefault(TControl control)
		{
			return object.Equals(this.DefaultValue, this.GetValue(control));
		}
		/// <summary>
		/// Deserializes the value of this property from the specified <see cref="JsonReader"/>.
		/// </summary>
		/// <param name="control"></param>
		/// <param name="jr"></param>
		public override void DeserializeValue(TControl control, TA.JSON.JsonReader jr)
		{
			T t = default(T);
			if (jr.Value is T)
			{
				t = (T)jr.Value;
			}
			else
			{
				try
				{
					t = (T)Convert.ChangeType(jr.Value, typeof(T));
				}
				catch
				{
					throw new Exception("Failed to deserialize value for property " + this.Name);
				}
			}
			this.SetValue(control, t);
		}
		#endregion
		#endregion
		#region INTERNAL
		#region VARS
		T _defaultValue;
		#endregion
		#region PROPS
		#endregion
		#region METHODS
		/// <summary>
		/// Gets the value of this property for the specified control.
		/// </summary>
		/// <param name="control"></param>
		/// <returns></returns>
		protected internal virtual T GetValue(TControl control)
		{
			if (control._State[this.Name] == null)
			{
				return this.GetDefaultValue(control);
			}
			return (T)control._State[this.Name];
		}
		/// <summary>
		/// Gets the default value for this property for the specified control.
		/// </summary>
		/// <param name="control"></param>
		/// <returns></returns>
		protected virtual T GetDefaultValue(TControl control)
		{
			return this.DefaultValue;
		}
		/// <summary>
		/// Sets the value of this property for the specified control.
		/// </summary>
		/// <param name="control"></param>
		/// <returns></returns>
		protected virtual void SetValue(TControl control, T value)
		{
			control._State[this.Name] = value;
		}
		#endregion
		#endregion
	}
}
